﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using System.Windows.Forms;
using System.ComponentModel;

namespace Cheetah_Fast_Banking_App
{
    public class CommandRelayer : INotifyPropertyChanged
    {
        #region Properties
        /// <summary>
        /// Currently Selected account.  Used for databinding.
        /// OnProperty triggers update to databound objects
        /// </summary>
        public Account SelectedAccount
        {
            get { return _selectedAccount; }
            set
            {
                _selectedAccount = value;
                OnPropertyChanged("SelectedAccount");
            }
        }
        private Account _selectedAccount = null;

        public bool IsValidAccount
        {
            get { return _selectedAccount != null; }
        }
        #endregion // Properties

        #region Constructor

        /// <summary>
        /// Parameterless for Databinding with XAML
        /// </summary>
        public CommandRelayer()
        {
            bool success = DataSourceSingleton.GetInstance().SetDataSource(Properties.Settings.Default.LastXmlPath);
        }

        #endregion // Constructor

        #region RelayCommand Methods

        /// <summary>
        /// Method to determine when a new transaction can be created
        /// </summary>
        /// <returns>bool indicating if action is enabled</returns>
        public bool CanCreateNewTransactionExecute()
        {
            //TODO: Change create based on user permission rather than any time there is a current account
            return _selectedAccount != null;
        }

        /// <summary>
        /// Execute method for new transaction event
        /// </summary>
        public void NewTransactionExecute()
        {
            NewTransactionForm TransForm = new NewTransactionForm();
            DialogResult Result = TransForm.ShowDialog();
            if (Result == DialogResult.OK)
            {
                _selectedAccount.SaveNewTransaction(TransForm.GetNewTransaction());
                TransForm.Dispose();
            }
        }

        /// <summary>
        /// ICommand for NewTransaction
        /// </summary>
        public ICommand UpdateNewTransaction
        {
            get { return new RelayCommand(NewTransactionExecute, CanCreateNewTransactionExecute); }
        }

        /// <summary>
        /// Determines when a transaction can be deleted
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        bool CanDeleteTransaction(object parameter)
        {
            // Only allow deleting when account is logged into
            return _selectedAccount != null;
        }

        /// <summary>
        /// Method to delete a transaction
        /// </summary>
        /// <param name="transaction">transaction to delete</param>
        void DeleteTransactionExecute(object transaction)
        {
            Transaction trans = transaction as Transaction;
            if ((trans != null) && (_selectedAccount != null))
            {
                _selectedAccount.DeleteTransaction(trans);
            }
        }

        /// <summary>
        /// ICommand for Delete Transaction
        /// </summary>
        public ICommand UpdateDeleteTransaction
        {
            get { return new RelayCommand<object>(DeleteTransactionExecute, CanDeleteTransaction); }
        }

        /// <summary>
        /// Determines when Login is enabled
        /// </summary>
        /// <returns>bool</returns>
        public bool CanLoginExecute()
        {
            return !IsValidAccount;
        }

        /// <summary>
        /// Executes login procedures
        /// </summary>
        public void LoginExecute()
        {
            FormLogin login = new FormLogin();

            do
            {
                DialogResult result = login.ShowDialog();
                if (result != DialogResult.OK)
                {
                    // User closed the window--exit the login process
                    break;
                }

                // Login button pressed--validate credentials
                SelectedAccount = DataSourceSingleton.GetInstance().ValidateCredentials(login.AccountName, login.PasswordHash);
                if (login.DialogResult == DialogResult.OK && !IsValidAccount)
                {
                    login.InvalidCredentials();
                }
                else if (login.DialogResult == DialogResult.OK && IsValidAccount)
                {
                    login.Dispose();
                }
            } while (!IsValidAccount);
        }

        /// <summary>
        /// ICommand for Login
        /// </summary>
        public ICommand UpdateLogin
        {
            get { return new RelayCommand(LoginExecute, CanLoginExecute); }
        }

        /// <summary>
        /// Determines when change data is enabled
        /// <returns>bool</returns>
        public bool CanChangeDataExecute()
        {
            return true;
        }

        /// <summary>
        /// Executes change data procedures
        /// </summary>
        public void ChangeDataExecute()
        {
            OpenFileDialog browseFile = new OpenFileDialog();
            browseFile.Filter = "XML Files (*.xml)|*.xml";
            browseFile.Title = "Browse XML file";
            if (browseFile.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            try
            {
                bool successful = DataSourceSingleton.GetInstance().SetDataSource(browseFile.FileName);
                if (!successful)
                {
                    MessageBox.Show("File is not properly formatted", "File Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else
                {
                    DataSourceSingleton.GetInstance().RefreshXmlData();
                    SelectedAccount = null;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "File Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        /// <summary>
        /// ICommand for Login
        /// </summary>
        public ICommand UpdateChangeData
        {
            get { return new RelayCommand(ChangeDataExecute, CanChangeDataExecute); }
        }

        public bool CanOpenAccountExecute()
        {
            // TODO: Currently no permissions for being able to open accounts
            return true;
        }

        public void OpenAccountExecute()
        {
            FormOpenAccount formOpenAccount = new FormOpenAccount();
            formOpenAccount.ShowDialog();
            formOpenAccount.Dispose();
        }

        public ICommand UpdateOpenAccount
        {
            get { return new RelayCommand(OpenAccountExecute, CanOpenAccountExecute); }
        }

        public bool CanModifyAccountExecute()
        {
            // TODO: Currently no permissions for being able to modify accounts
            return true;
        }

        public void ModifyAccountExecute()
        {
            FormModifyAccount formModifyAccount = new FormModifyAccount();
            formModifyAccount.ShowDialog();
            formModifyAccount.Dispose();
        }

        public ICommand UpdateModifyAccount
        {
            get { return new RelayCommand(ModifyAccountExecute, CanModifyAccountExecute); }
        }

        public bool CanLogoutExecute()
        {
            return IsValidAccount;
        }

        public void LogoutExecute()
        {
            SelectedAccount = null;
        }

        public ICommand UpdateLogout
        {
            get { return new RelayCommand(LogoutExecute, CanLogoutExecute); }
        }

        #endregion RelayCommand Methods

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion
    }
}
